package org.easy.tool.service;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.easy.tool.common.LogUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class BackupService {
    @Value("${spring.datasource.username}") private String username;
    @Value("${spring.datasource.password}") private String password;
    @Value("${westudy.backup.dir}") private String backupDir;
    @Value("${westudy.backup.max-age}") private Duration maxAge;
    @Value("${westudy.backup.db-host}") private String host;
    @Value("${westudy.backup.db-port}") private String port;
    @Value("${westudy.backup.db-name}") private String dbName;

    private final Lock lock = new ReentrantLock();

    public Path backup() throws Exception {
        if (!lock.tryLock()) throw new Exception("已有备份任务运行中");
        try {
            // 生成带时间戳的文件名
            String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".sql";
            Path filePath = Paths.get(backupDir, fileName);
            Files.createDirectories(filePath.getParent());
            
            // 构建mysqldump命令
            String command = String.format("mysqldump -h %s -P %s -u %s -p%s %s",
                    host, port, username, password, dbName);

            // 执行命令并写入文件
            try (FileOutputStream outputStream = new FileOutputStream(filePath.toFile())) {
                CommandLine cmdLine = CommandLine.parse(command);
                DefaultExecutor executor = new DefaultExecutor();

                // 设置超时（1小时）和流处理
                ExecuteWatchdog watchdog = new ExecuteWatchdog(TimeUnit.HOURS.toMillis(1));
                executor.setWatchdog(watchdog);
                executor.setStreamHandler(new PumpStreamHandler(outputStream, System.err));

                // 执行备份
                int exitCode = executor.execute(cmdLine);
                if (exitCode != 0) {
                    throw new Exception("备份失败，退出码: " + exitCode);
                }
            }

            return filePath;
        } finally {
            lock.unlock();
        }
    }
}